﻿using System.Collections.Concurrent;
using System.Linq;
using CnSharp.Database.Core;
using CnSharp.Database.MsSql;
using CnSharp.Database.Objects;
using CnSharp.SSMS.AddIn.Util;

namespace CnSharp.SSMS.AddIn.Framework.Cache
{
    public class ObjectCache : IObjectCache
    {
        public bool Processing { get; private set; }
        private readonly ConcurrentDictionary<string,Database.Objects.Database> _databases = new ConcurrentDictionary<string, Database.Objects.Database>();
        private static  ObjectCache _cache;
        public static IObjectCache Instance
        {
            get { return _cache ?? (_cache = new ObjectCache()); }
        }


        public Database.Objects.Database Get(string server, string databaseName)
        {
            //var fileName = Path.Combine(dir, server, databaseName);
            //return CnSharp.Xml.XmlSerializerHelper.LoadObjectFromXml<Database>(fileName);
            var key = GetKey(server, databaseName);
            Database.Objects.Database db;
            _databases.TryGetValue(key, out db);
            return db;
        }

        public Table  GetTable(DbObjectContext context)
        {
            var db = Get(context.Server, context.Database);
            if (db == null)
                return null;
            return db.Tables.FirstOrDefault(m => m.Name == context.Name);
        }

        public View GetView(DbObjectContext context)
        {
            var db = Get(context.Server, context.Database);
            if (db == null)
                return null;
            return db.Views.FirstOrDefault(m => m.Name == context.Name);
        }

        public ProgramScript GetStoredProcedure(DbObjectContext context)
        {
            var db = Get(context.Server, context.Database);
            if (db == null)
                return null;
            return db.Procedures.FirstOrDefault(m => m.Name == context.Name);
        }

        private string GetKey(string server, string dbName)
        {
            return server + "." + dbName;
        }

        public void Cache(string server, string dbName,string connectionString)
        {
            Processing = true;

            try
            {
                var dbServer = new MsSql(connectionString);

                //var dbs = dbServer.GetDatabases();
                //var dbList = new List<Database>();

                //dir = Path.Combine(dir, server);
                //if (!Directory.Exists(dir))
                //    Directory.CreateDirectory(dir);

                //foreach (var dbName in dbs)
                //{
                //    dbServer.ChangeDB(dbName);
                var db = new Database.Objects.Database();
                db.Tables = dbServer.GetTables(TableItemOptions.Column);
                db.Views = dbServer.GetViews();
                db.Procedures = dbServer.GetProcedures();
                db.Functions = dbServer.GetFunctions();
                //dbList.Add(db);

                _databases.AddOrUpdate(GetKey(server,dbName), db, (key, oldValue) => db);
                //var fileName = dir + dbName + ".xml";
                //FileIO.WriteText(fileName,CnSharp.Xml.XmlSerializerHelper.GetXmlStringFromObject(db));
                //}

            }
            finally
            {
                Processing = false;
            }


        }

        public void Update(string server, string dbName, Table table)
        {
            if (Processing)
                return;
            var db = Get(server, dbName);
            if (db == null)
                return;
            db.Tables.RemoveAll(m => m.Name == table.Name);
            db.Tables.Add(table);
            db.Tables = db.Tables.OrderBy(m => m.Name).ToList();
        }
    }
}
